package com.stylefeng.guns.modular.system.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateTime;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.stylefeng.guns.core.base.controller.BaseController;
import com.stylefeng.guns.core.base.tips.ErrorTip;
import com.stylefeng.guns.core.base.tips.Tip;
import com.stylefeng.guns.core.cache.CacheKit;
import com.stylefeng.guns.core.common.Tools.Result;
import com.stylefeng.guns.core.common.annotion.BussinessLog;
import com.stylefeng.guns.core.common.constant.dictmap.RoleDict;
import com.stylefeng.guns.core.common.constant.state.SpType;
import com.stylefeng.guns.core.common.exception.BizExceptionEnum;
import com.stylefeng.guns.core.exception.GunsException;
import com.stylefeng.guns.core.log.LogObjectHolder;
import com.stylefeng.guns.core.model.SysFunTree;
import com.stylefeng.guns.core.shiro.ShiroUser;
import com.stylefeng.guns.core.support.HttpKit;
import com.stylefeng.guns.core.util.JwtTokenUtil;
import com.stylefeng.guns.core.util.ToolUtil;
import com.stylefeng.guns.core.validater.Insert;
import com.stylefeng.guns.core.validater.Update;
import com.stylefeng.guns.modular.system.model.*;
import com.stylefeng.guns.modular.system.service.*;
import com.stylefeng.guns.modular.system.warpper.PostWarpper;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.commons.collections.FastArrayList;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.inject.Inject;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;

/**
 * 岗位管理控制器
 *
 * @author fengshuonan
 * @Date 2018-09-04 17:59:21
 */
@Controller
@RequestMapping(value = {"/gunsApi/auth/post"})
@Api(value = "系统岗位接口类", tags = {"系统岗位接口类"})
public class PostController extends BaseController {

    private String PREFIX = "/system/post/";

    @Autowired
    private IPostService postService;
    
    @Autowired
    private IPostPathService postPathService;
    
    @Autowired
    private IUserCwService userCwService;
    
    @Autowired
    private IOrgService orgService;
    
    @Resource
    private IFunctionService functionService;
    
    @Inject
    private ISysPrivilegeService sysPrivilegeService;
    
    @Inject
    private IOrgcategoryFunctionService orgcategoryFunctionService;
    
    private static final String CACHE_STRATEGY = "local";

    /**
     * 跳转到岗位管理首页
     */
    @RequestMapping("")
    public String index() {
        return PREFIX + "post.html";
    }

    /**
     * 跳转到添加岗位管理
     */
    @RequestMapping("/post_add")
    public String postAdd() {
        return PREFIX + "post_add.html";
    }

    /**
     * 跳转到修改岗位管理
     */
    @RequestMapping("/post_update/{postId}")
    public String postUpdate(@PathVariable Integer postId, Model model) {
        Post post = postService.selectById(postId);
        model.addAttribute("item", post);
        LogObjectHolder.me().set(post);
        return PREFIX + "post_edit.html";
    }

    /**
     * 获取岗位管理列表
     */
    @ApiOperation(value = "获取岗位管理列表", notes = "获取岗位管理列表", httpMethod = "GET")
    @GetMapping("/list")
    @ResponseBody
    public Result list(@ApiParam(name = "condition", value = "岗位名称", type = "String", required = false) @RequestParam(value = "condition",required = false)  String condition,
                       @RequestParam(value = "soId",required = false) @ApiParam(name = "soId", value = "机构ID") Integer soId,
                       @ApiParam(name = "pageNum", value = "当前页数", required = false) @RequestParam(value = "pageNum", defaultValue = "1",required = false) Integer pageNum,
                       @ApiParam(name = "pageSize", value = "每页显示条数", required = false) @RequestParam(value = "pageSize", defaultValue = "10000",required = false) Integer pageSize) {
        Page<Post> page = new Page<Post>(pageNum,pageSize);
        Wrapper<Post> wrapper=new EntityWrapper<>();
        if(ToolUtil.isNotEmpty(soId))
            wrapper.eq("so_id",soId);
        String accout=this.getShiroUser().getAccount();
        if (StringUtils.isNotEmpty(accout) && !StringUtils.equalsIgnoreCase("admin", accout)) {
            int soId_ = getShiroUser().getSoId();
                if (ToolUtil.isNotEmpty(soId_)) {
                    Wrapper<Org> orgWrapper = new EntityWrapper<>();
                    orgWrapper.eq("so_id", soId_).or();
                    orgWrapper.like("so_pids", "%[" + soId_ + "]%");
                    List<Org> list = this.orgService.selectList(orgWrapper);
                        if (list != null && list.size() > 0) {
                            List<Integer> soIdList =list.stream().map(Org::getSoId).collect(Collectors.toList());
             if (soIdList != null && soIdList.size() > 0) {
                wrapper.and().in("so_id", soIdList);
          }
        }
      }
        }
        if(StringUtils.isNotBlank(condition))
            wrapper.like("sp_name", condition);
        page=this.postService.selectPage(page,wrapper);
        List<Post> list=page.getRecords();
        List<Map<String, Object>> mList=new ArrayList<>();
        for (Post o:list){
            Map m= BeanUtil.beanToMap(o);
            mList.add(m);
        }
        super.warpObject(new PostWarpper(mList));//包裹实体类
        BeanUtil.setFieldValue(page,"records",mList);//注入实体对象
        return Result.success(page);
    }

    /**
     * 新增岗位管理
     */
    @ApiOperation(value = "添加岗位", notes = "添加岗位", httpMethod = "POST")
    @PostMapping(value = "/add", consumes = MediaType.APPLICATION_JSON_UTF8_VALUE, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ResponseBody
    @BussinessLog("添加岗位")
    public Object add(@Validated(value = Insert.class) @RequestBody @ApiParam(name = "post", value = "新增岗位", required = true) Post post, BindingResult result) {
        if (result.hasErrors()) {
            throw new GunsException(BizExceptionEnum.REQUEST_NULL);
        }
        Post p = new Post();
        PostPath postPath=new PostPath();
        Integer soid=post.getSoId();
        p.setSpName(post.getSpName());
        p.setSoId(soid);
        List<Post> list = (List<Post>) (Object) postService.selectObjs(new EntityWrapper<>(p));
        if (list != null && list.size() > 0) {//岗位已存在
            return new ErrorTip(BizExceptionEnum.POST_ALREADY_EXISTS.getCode(), BizExceptionEnum.POST_ALREADY_EXISTS.getMessage());
        }
      ShiroUser shiroUser=this.getShiroUser();
        Integer userCwId=shiroUser.getId();
        if(userCwId!=null){
            UserCw user=this.userCwService.selectById(userCwId);
            post.setCreateUser(user.getSuiName());
            post.setCreateTime(DateTime.now());
            postPath.setCreateUser(user.getSuiName());
            postPath.setCreateTime(DateTime.now());
        }
        //所属机构
        StringBuilder builder=new StringBuilder();
        Org org=this.orgService.selectById(soid);
        if(org!=null){
            String pids=org.getSoPids();
            builder.append(pids).append(soid);
            postPath.setSpPath(builder.toString());//设置机构全路径
        }
        boolean f = postService.insert(post);
        if (f) {
            post = this.postService.selectOne(new EntityWrapper<>(p));
            postPath.setSpId(post.getSpId());
            Wrapper<PostPath> wrapper=new EntityWrapper();
            this.postPathService.delete(wrapper.eq("sp_id",post.getSpId()));
            this.postPathService.insert(postPath);
            return Result.success();
        }
        else {
            return new ErrorTip(400, "插入失败");
        }
    }

    /**
     * 删除岗位管理
     */
    @ApiOperation(value = "删除岗位", notes = "删除岗位", httpMethod = "DELETE")
    @RequestMapping(value = "/delete",method=RequestMethod.DELETE)
    @ResponseBody
    @BussinessLog("删除岗位管理")
    public Object delete(@ApiParam(value = "岗位ID", name = "postId") @RequestParam(value = "postId") Integer postId) {
        Post post = this.postService.selectById(postId);
        if (post == null) {
            return new ErrorTip(BizExceptionEnum.POST_NOT_EXISTS.getCode(), BizExceptionEnum.POST_NOT_EXISTS.getMessage());
        }
        Wrapper<PostPath> wrapper=new EntityWrapper<>();
        wrapper.like("sp_path",postId+"");
        List<PostPath> list=this.postPathService.selectList(wrapper);
        CopyOnWriteArrayList<PostPath> cpList=new CopyOnWriteArrayList<>(list);
        if (!list.isEmpty()){
         for(PostPath pp:cpList){
             if(StringUtils.contains(pp.getSpPath(),postId+"")) {
                 this.postPathService.deleteById(pp.getSppId());
                 cpList.remove(pp);
             }
             else {
                 pp.setSpPath(StringUtils.remove(pp.getSpPath(), postId+""));
             }
         }
        }
        this.postService.deleteById(postId);
        return SUCCESS_TIP;
    }

    /**
     * 批量删除岗位
     */
    @ApiOperation(value = "批量删除岗位", notes = "批量删除岗位", httpMethod = "DELETE")
    @RequestMapping(value = "/BatchDel",method=RequestMethod.DELETE)
    @ResponseBody
    @BussinessLog("批量删除岗位")
    public Object BatchDel(@ApiParam(value = "岗位ID集", name = "postIds") @RequestParam(value = "postIds") String... postIds) {
        for(String i:postIds) {
            Post post = this.postService.selectById(i);
            if (post == null) {
                return new ErrorTip(BizExceptionEnum.POST_NOT_EXISTS.getCode(), BizExceptionEnum.POST_NOT_EXISTS.getMessage());
            }
        }
        Wrapper<PostPath> wrapper = new EntityWrapper<>();
        wrapper.in("sp_id",Arrays.asList(postIds));
        this.postPathService.delete(wrapper);
        this.postService.deleteBatchIds(Arrays.asList(postIds));
        return SUCCESS_TIP;
    }

    /**
     * 修改岗位管理
     */
    @ApiOperation(value = "岗位更新", notes = "岗位更新", httpMethod = "POST")
    @ApiImplicitParam(name = "post", value = "岗位实体post", required = true, dataType = "Post")
    @PostMapping(value = "/update")
    @ResponseBody
    public Object update(@Validated(value = Update.class) @ApiParam(name = "post", value = "岗位对象", required = true) @RequestBody Post post) {
        ShiroUser shiroUser=this.getShiroUser();
        Integer userCwId=shiroUser.getId();
        if(userCwId!=null){
            UserCw user=this.userCwService.selectById(userCwId);
            post.setUpdateUser(user.getSuiName());
            post.setUpdateTime(DateTime.now());
        }
        Boolean f = postService.updateById(post);
        if (f)
            return SUCCESS_TIP;
        else
            return new ErrorTip(401, "更新失败");
    }
    
    
    /**
     * 岗位配置权限(成为)
     */
    @ApiOperation(value="配置权限",notes = "配置权限",httpMethod = "GET")
    @GetMapping("/setAuthority")
    @BussinessLog(value = "岗位权限配置", key = "postId,ids", dict = RoleDict.class)
    @ResponseBody
    public Object setAuthority(@ApiParam(name = "postId", value = "岗位ID", required = true) @RequestParam("postId") Integer postId,
                            @ApiParam(name = "ids", value = "功能权限ID集", required = true) @RequestParam("ids") String ids) {
        if (ToolUtil.isOneEmpty(postId,ids)) {
            throw new GunsException(BizExceptionEnum.REQUEST_NULL);
        }
        Post post=this.postService.selectById(postId);
        
        if(post==null){
            throw new GunsException(BizExceptionEnum.NO_THIS_POST);
        }
        this.postService.setAuthority(postId,ids);
        return SUCCESS_TIP;
    }
    
    /**
     *岗位层级设置
     */
    @ApiOperation(value="岗位层级关系设定",notes = "岗位层级关系设定",httpMethod ="POST")
    @PostMapping("/setLevel")
    @BussinessLog("岗位层级设置")
    @ResponseBody
   public Tip setLevelDef(@Validated(value = Insert.class) @RequestBody PostPath postPath, BindingResult result){
        if (result.hasErrors()){
            throw new GunsException(BizExceptionEnum.REQUEST_NULL);
        }
        //所属机构
        Integer soid=postPath.getSoId();
        StringBuilder builder=new StringBuilder();
        Org org=this.orgService.selectById(soid);
        if(org!=null){
            String pids=org.getSoPids();
            builder.append(pids).append(soid);
            postPath.setSpPath(builder.toString());//设置机构全路径
        }
        String token= HttpKit.getRequest().getHeader("Authorization").substring(7);
        String subject = JwtTokenUtil.getClaimFromToken(token).getSubject();//用户ID
        if(StringUtils.isNotEmpty(subject)){
            UserCw user=this.userCwService.selectById(subject);
            postPath.setCreateUser(user.getSuiName());
            postPath.setCreateTime(DateTime.now());
        }
        Wrapper<PostPath> wrapper=new EntityWrapper();
        this.postPathService.delete(wrapper.eq("sp_id",postPath.getSpId()));
        this.postPathService.insert(postPath);
        return SUCCESS_TIP;
    }

    /**
     * 岗位管理详情
     */
    @ApiOperation(value = "岗位详情", notes = "岗位详情", httpMethod = "GET")
    @RequestMapping(value = "/detail",method = RequestMethod.GET)
    @ResponseBody
    public Result detail(@ApiParam(name = "postId", value = "岗位ID", required = true) @RequestParam("postId") Integer postId) {
        return Result.success(postService.selectById(postId));
    }
    
    
    /**
     * 岗位权限列表
     */
    @ApiOperation(value = "岗位权限列表", notes = "岗位权限列表", httpMethod = "GET")
    @GetMapping(value = "/privilege")
    @ResponseBody
    public Result privilege(@ApiParam(name = "type", value = "是否过滤菜单(0:不过滤 1:过滤)", required = true) Integer type,@ApiParam(name = "postIds", value = "岗位ID集", required = true) @RequestParam("postIds") Integer... postIds) {
        if (ToolUtil.isNotEmpty(postIds)){
            return Result.success(functionService.getMenusByPostIds(Arrays.asList(postIds),type));
        }else{
            return Result.error(new ErrorTip(404,"岗位ID为空"));
        }
     
    }
    /**
     * 根据机构分类角色查询所拥有的功能和操作
     */
    @ApiOperation(value="机构分类角色查询所拥有的功能和操作",notes = "机构分类角色查询所拥有的功能和操作",httpMethod ="POST")
    @PostMapping(value = "/selectList")
    @ResponseBody
    public Result selectListOrgcategoryRoleFunction(@ApiParam(name = "post", value = "角色实体", required = true) @RequestBody Post post,BindingResult result){
        if (result.hasErrors()) {
            throw new GunsException(BizExceptionEnum.REQUEST_NULL);
        }
        //返回权限树
        List<SysFunTree> listSysFun = new ArrayList<>();
        // 获取机构分类ID
        Integer soId=post.getSoId();
        Org org=this.orgService.selectById(soId);
        String orgcategoryid="";
        if(ToolUtil.isNotEmpty(org))
            orgcategoryid = org.getSoCate();
        
        // 获取当前角色所有功能
        Wrapper<SysPrivilege> wrapper=new EntityWrapper<>();
        wrapper.eq("sp_type", SpType.POSITION.getCode()).and();
        wrapper.eq("sp_type_id",post.getSpId());
        List<SysPrivilege> list = this.sysPrivilegeService.selectList(wrapper);
        List<Integer> idList=new FastArrayList();
        List<Function> listSysCategoryRoleFun=new ArrayList<>();
        if(list!=null&&list.size()>0){
            idList=list.parallelStream().sorted(Comparator.comparing(SysPrivilege::getSpFunctionId)).map(SysPrivilege::getSpFunctionId).collect(Collectors.toList());
            listSysCategoryRoleFun=this.functionService.selectBatchIds(idList);
        }
     
        // 根据机构分类，获取机构功能树
        List<OrgcategoryFunction> listSysCategoryFun = orgcategoryFunctionService.selectListOrgcategoryFunction(orgcategoryid);
        if (listSysCategoryFun != null && listSysCategoryFun.size()>0) {
            for (OrgcategoryFunction tempOrgCateFun:listSysCategoryFun) {
                SysFunTree sysFunTree = new SysFunTree();
                sysFunTree.setChecked("false");
                for(Function roleFunction:listSysCategoryRoleFun){
                    if(roleFunction.getSfId()==tempOrgCateFun.getSpFunctionId().intValue()){
                        sysFunTree.setChecked("true");
                        break;
                    }
                }
                sysFunTree.setId(""+tempOrgCateFun.getSpFunctionId());
                sysFunTree.setPid(tempOrgCateFun.getSpFunctionPid());
                sysFunTree.setName(tempOrgCateFun.getSpFunctionName());
                if(tempOrgCateFun.getSfIsmenu().equals("1")){
                    sysFunTree.setFunType("F");//tree节点表示功能
                }else{
                    sysFunTree.setFunType("M");//tree节点表示功能
                }
                listSysFun.add(sysFunTree);
            }
        }
        listSysCategoryRoleFun.clear();
        listSysCategoryFun.clear();
        return Result.success(listSysFun);
    }

    @Cacheable(value="local",key = "'userCw_'+#result.getId()")
    public  ShiroUser getShiroUser(){
        String token= getHttpServletRequest().getHeader("Authorization").substring(7);
        return CacheKit.get(CACHE_STRATEGY,token);
    }
    
}
